home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Whiteline: delta
/
whiteline CD Series - delta.iso
/
progtool
/
modula2
/
module
/
easywind.mod
< prev
next >
Wrap
Text File
|
1995-11-25
|
27KB
|
860 lines
IMPLEMENTATION MODULE EasyWindow;
FROM SYSTEM IMPORT TSIZE, VAL,ADDRESS,SHIFT,SHORT,ADR,BYTE;
FROM Storage IMPORT ALLOCATE,DEALLOCATE;
FROM GEMVDIbase IMPORT PxyArrayType, BigPxyArrayType, TextAttrArrayType;
FROM VDIRasters IMPORT CopyRasterOpaque,MFDBType,MFDBptr;
FROM VDIControls IMPORT SetClipping;
FROM VDIAttribs IMPORT SetFillStyle,SetFillColour,SetFillInteriorStyle,
SetGraphicTextColour,SetGraphicTextEffects;
FROM VDIInquires IMPORT InquireFillAttributes,InquireTextAttributes;
FROM VDIOutputs IMPORT DrawBar,GraphicText;
FROM GEMAESbase IMPORT WindowRedraw, WindowTopped, WindowClosed, WindowFulled,
WindowArrowed, WindowHorizSlided, WindowVertSlided,
WindowSized, WindowMoved, WindowNewTop, WindowKind,
WindowName, WindowInfo, WorkXYWH, CurrXYWH, PrevXYWH,
FullXYWH, WindowHorizSlide, WindowVertSlide, Top,
FirstXYWH, NextXYWH, HorizSliderSize, VertSliderSize,
WindowScreen,White,Black,EndUpdate,BeginUpdate,WCWork,
WCBorder;
FROM AES IMPORT GrafMouse,FormDialogue,WindowFind,WindowGet,WindowDelete,
WindowClose,WindowSet,WindowUpdate,WindowCalc,WindowOpen,
GrafGrowBox,GrafShrinkBox,GrafHandle,WindowCreate,FormAlert;
VAR
WC,HC,WB,HB : INTEGER;
handle : INTEGER;
Nil2Max : INTEGER;
PROCEDURE TerminateWindows;
VAR w: INTEGER;
BEGIN
FOR w := 1 TO maxwindow DO
IF windowlist[w] # NIL THEN
IF windowlist[w]^.opened THEN
WindowClose(w);
END(*IF*);
DEALLOCATE(windowlist[w]);
WindowDelete(w);
END(*IF*);
END(*FOR*);
w:=SetGraphicTextColour(handle,Black);
w:=SetGraphicTextEffects(handle,VAL(INTEGER,NoEffects));
END TerminateWindows;
PROCEDURE createWindow (VAR u: window;
x, y, w, h: INTEGER;
parts: WindowElements;
title: ARRAY OF CHAR;
textwindow: BOOLEAN;
rdp: RedrawProcType);
VAR win :windowtype;
i,wx,wy,ww,wh: INTEGER;
t : wstring;
BEGIN
IF HIGH(title)>78 THEN
FOR i:= 0 TO 78 DO
t[i]:=title[i]
END(*FOR*);
t[79]:=0C
ELSE
FOR i:= 0 TO HIGH(title) DO
t[i]:=title[i]
END(*FOR*);
t[HIGH(title)+1]:=0C
END(*IF*);
IF (w=0) OR (h=0) THEN
WindowGet(0,WorkXYWH,wx,wy,ww,wh);
u:=WindowCreate(VAL(INTEGER,parts),wx,wy,ww,wh);
WindowCalc(WCWork,VAL(INTEGER,parts),wx,wy,ww,wh,x,y,w,h);
WindowCalc(WCBorder,VAL(INTEGER,parts),x,y,w,h,wx,wy,ww,wh);
ELSE
WindowCalc(WCBorder,VAL(INTEGER,parts),x,y,w,h,wx,wy,ww,wh);
u:=WindowCreate(VAL(INTEGER,parts),wx,wy,ww,wh);
END(*IF*);
IF (u>0) AND (u<maxwindow) THEN
win.handle:=u;
win.max.x:=wx;
win.max.y:=wy;
win.max.w:=ww;
win.max.h:=wh;
win.work.x:=x;
win.work.y:=y;
win.work.w:=w;
win.work.h:=h;
win.total.x:=wx;
win.total.y:=wy;
win.total.w:=ww;
win.total.h:=wh;
win.min.x:=wx;
win.min.y:=wy;
win.min.w:=10*WC;
win.min.h:=6*HC;
win.elements:=parts;
win.fulled:=FALSE;
win.opened:=FALSE;
win.ontop:=FALSE;
win.text:=textwindow;
win.grow:=growbox;
win.snap:=Snap;
IF textwindow THEN
win.allignX:=WC;
win.allignY:=HC;
win.scrollX:=WC;
win.scrollY:=HC;
ELSE
win.allignX:=AllignX;
win.allignY:=AllignY;
win.scrollX:=WC;
win.scrollY:=HC;
END(*IF*);
win.row:=1;win.col:=1;
win.maxrow:=1;
win.maxcol:=1;
win.colour:=White;
win.InteriorStyle:=1C;
win.FillStyle:=1C;
win.textcolour:=Black;
win.texteffects:=NoEffects;
win.redrawproc:=rdp;
win.title:=t;
win.info:=0C;
win.reference:=NIL;
ALLOCATE(windowlist[u],TSIZE(windowtype));
windowlist[u]^:=win;
SetTitle(u,title);
ELSE
t:="[3][Zu viele Fenster offen][Abbruch]";
x:=FormAlert(1,t);
END(*IF*);
END createWindow;
(* Erzeugt die im AES und in diesem Modul notwendigen Datenstrukturen
zur Verwaltung eines Fensters, das jedoch noch nicht gezeichnet
wird.
x, y, w und h beschreiben die maximale Grösse des äusseren Fenster-
randes. Sind w oder h gleich 0, so wird die Grösse des Desktops
ohne Menüleiste übernommen.
"parts" ist ein Set aus den gewünschten Fensterelementen.
"title" ist der Fenstertitel.
"textwindow" soll bei Textfenstern auf TRUE gesetzt werden,
der Fensterursprung wird dann an das Textraster angepaßt.
"rdp" ist die Redraw-Prozedur, also die Prozedur, die den Inhalt
des Fensters zeichnet. Sie wird beim Aufruf der Prozedur "DoRedraw"
(siehe unten) so oft aufgerufen wird, bis die Rechteckliste, die
die sichtbaren Teile des Fensters angibt, abgearbeitet worden ist.
An "rdp" wird beim Aufruf ein Rechteck übergeben, das die neu
zu zeichnende Fläche angibt. Wurde beim Aufruf von "DoRedraw"
der Paramter "clip" auf FALSE gesetzt, muss "rdp" alle Ausgaben
selbst auf diese Fläche begrenzen, was die Ausgabe vor allem bei
Text stark beschleunigen kann, aber bei teilweise verdeckten Fen-
stern kaum durchführbar ist. Beim Zeichnen von Objektbäumen wird
das Begrenzungsrechteck direkt beim "ObjectDraw"-Aufruf angegeben.
*)
PROCEDURE clearWindow (u: window );
VAR win : windowtype;
rect :rectangle;
BEGIN
IF windowlist[u] # NIL THEN
win:=windowlist[u]^;
IF win.opened THEN
WindowGet(u,WorkXYWH,rect.x,rect.y,rect.w,rect.h);
rect.x:=0;rect.y:=0;
clearrect(u,rect);
END(*IF*);
END(*IF*);
END clearWindow;
PROCEDURE clearrect (u: window ; rect: rectangle);
VAR win : windowtype;
pxy : PxyArrayType;
Bpxy :BigPxyArrayType;
c,s,x,y,w,h:INTEGER;
BEGIN
IF windowlist[u] # NIL THEN
win:=windowlist[u]^;
IF win.opened THEN
WindowGet(u,WorkXYWH,x,y,w,h);
rect.x:=rect.x+x;
rect.y:=rect.y+y;
RectToPxy(rect,pxy);
(* Derzeitige Füllatribute und Farben erfragen *)
InquireFillAttributes(handle,Bpxy);
MouseOff;
c:=SetFillColour(handle,win.colour);
s:=SetFillStyle (handle,VAL(INTEGER,win.FillStyle));
s:=SetFillInteriorStyle (handle,VAL(INTEGER,win.InteriorStyle));
DrawBar(handle,pxy);
(* Füll-Atribute u. -Farbe wierherstellen *)
c:=SetFillColour(handle,Bpxy[1]);
s:=SetFillStyle (handle,Bpxy[2]);
s:=SetFillInteriorStyle (handle,Bpxy[0]);
MouseOn;
END(*IF*);
END(*IF*);
END clearrect;
(* Löscht einen Rechteckbereich innerhalb des Fensters "u" in
Fensterkoordinaten *)
PROCEDURE closeWindow (u: window );
VAR win : windowtype;
x,y,w,h :INTEGER;
BEGIN
IF windowlist[u] # NIL THEN
win:=windowlist[u]^;
IF win.opened THEN
WindowGet(u,CurrXYWH,x,y,w,h);
IF win.grow THEN
GrafShrinkBox(x,y,WC,HC,x,y,w,h)
END(*IF*);
WindowClose(u);
END(*IF*);
win.opened:=FALSE;
win.ontop:=FALSE;
windowlist[u]^:=win;
END(*IF*);
END closeWindow;
PROCEDURE deleteWindow (VAR u: window );
VAR win : windowtype;
BEGIN
IF windowlist[u] # NIL THEN
win:=windowlist[u]^;
IF win.opened THEN
WindowClose(u);
END(*IF*);
WindowDelete(u);
DEALLOCATE(windowlist[u]);
windowlist[u]:= NIL;
u:=-1
END(*IF*);
END deleteWindow ;
PROCEDURE fullWindow (u: window );
VAR win : windowtype;
x,y,w,h :INTEGER;
BEGIN
IF windowlist[u] # NIL THEN
win:=windowlist[u]^;
IF ~win.fulled THEN
IF win.grow THEN
WindowGet(u,CurrXYWH,x,y,w,h);
GrafGrowBox(x,y,w,h, win.max.x,win.max.y,win.max.w,win.max.h);
END(*IF*);
WindowSet(u,CurrXYWH,win.max.x,win.max.y,win.max.w,win.max.h);
win.fulled := TRUE
ELSE
WindowGet(u,PrevXYWH,x,y,w,h);
IF (x=win.max.x) AND (y=win.max.y) AND
(w=win.max.w) AND (h=win.max.h) THEN
x:=win.min.x;
y:=win.min.y;
w:=win.min.w;
h:=win.min.h;
END(*IF*);
IF win.grow THEN
GrafShrinkBox(x,y,w,h, win.max.x,win.max.y,win.max.w,win.max.h);
END(*IF*);
WindowSet(u,CurrXYWH,x,y,w,h);
win.fulled := FALSE
END(*IF*);
win.opened:=TRUE;
WindowGet(u,CurrXYWH,x,y,w,h);
win.total.x:=x;
win.total.y:=y;
win.total.w:=w;
win.total.h:=h;
WindowGet(u,WorkXYWH,x,y,w,h);
win.work.x :=x;
win.work.y :=y;
win.work.w :=w;
win.work.h :=h;
windowlist[u]^:=win;
END(*IF*);
END fullWindow;
PROCEDURE SnapWindow(u:window;VAR x,y,w,h:INTEGER);
(* Verkleinert das Fenster bei Verschiebungen so
das es vollständig auf dem Desktop zu sehen ist*)
VAR win:windowtype;
x0,y0,w0,h0 :INTEGER;
BEGIN
IF windowlist[u] # NIL THEN
win:=windowlist[u]^;
WindowGet(0,WorkXYWH,x0,y0,w0,h0);
IF (x+win.min.w)>(w0) THEN
x:=x0+w0-win.min.w
END(*IF*);
IF (y+win.min.h)>(h0) THEN
y:=y0+h0-win.min.h
END(*IF*);
IF (x+w) > (x0+w0) THEN
w:=x0+w0-x;
END(*IF*);
IF (y+h) > (y0+h0) THEN
h:=y0+h0-y;
END(*IF*);
END(*IF*);
END SnapWindow;
PROCEDURE AlignWindow(u:window;VAR x,y,w,h:INTEGER);
(* Passt das Fenster bei Verschiebungen an den
Snap-Wert an *)
VAR win : windowtype;
BEGIN
IF windowlist[u] # NIL THEN
win:=windowlist[u]^;
x:=x+SHIFT(win.allignX,-1)+1;
x:= win.allignX*(x DIV win.allignX);
y:=y+SHIFT(win.allignY,-1)+1;
y:= win.allignY*(y DIV win.allignY)
END(*IF*);
END AlignWindow;
PROCEDURE openWindow (u: window ; x, y, w, h: INTEGER);
VAR win:windowtype;
BEGIN
IF windowlist[u] # NIL THEN
win:=windowlist[u]^;
IF (w=0) OR (h=0) THEN
IF win.grow THEN
GrafGrowBox(x,y,w,h, win.total.x,win.total.y,win.total.w,win.total.h);
END(*IF*);
WindowOpen(u,win.total.x,win.total.y,win.total.w,win.total.h);
ELSE
IF win.grow THEN
GrafGrowBox(x+(w DIV 2),y+(h DIV 2),WC,HC,x,y,w,h)
END(*IF*);
WindowOpen(u,x,y,w,h);
END(*IF*);
WindowGet(u,CurrXYWH,x,y,w,h);
win.total.x:=x;
win.total.y:=y;
win.total.w:=w;
win.total.h:=h;
win.opened:=TRUE;
WindowGet(u,WorkXYWH,x,y,w,h);
win.work.x :=x;
win.work.y :=y;
win.work.w :=w;
win.work.h :=h;
windowlist[u]^:=win;
WindowGet(u,Top,u,y,w,h);
topWindow(u);
END(*IF*);
END openWindow;
PROCEDURE setWindow (u:window ; x, y, w, h: INTEGER);
VAR win : windowtype;
BEGIN
IF windowlist[u] # NIL THEN
win:=windowlist[u]^;
IF (win.allignX#1) OR (win.allignY#1) THEN
AlignWindow(u,x,y,w,h)
END(*IF*);
IF win.snap THEN SnapWindow(u,x,y,w,h) END(*IF*);
IF win.min.w>w THEN w:=win.min.w END(*IF*);
IF win.min.h>h THEN h:=win.min.h END(*IF*);
WindowSet(u,CurrXYWH,x,y,w,h);
win.total.x:=x;
win.total.y:=y;
win.total.w:=w;
win.total.h:=h;
WindowGet(u,WorkXYWH,x,y,w,h);
win.work.x :=x;
win.work.y :=y;
win.work.w :=w;
win.work.h :=h;
windowlist[u]^:=win;
END(*IF*);
END setWindow;
PROCEDURE topWindow (u: window );
VAR win : windowtype;
i : INTEGER;
BEGIN
IF windowlist[u] # NIL THEN
win:=windowlist[u]^;
WindowSet(u,Top,u,0,0,0);
win.opened:=TRUE;
win.ontop:=TRUE;
windowlist[u]^:=win;
FOR i:= 0 TO maxwindow DO
IF windowlist[i] # NIL THEN
win:=windowlist[i]^;
IF win.handle#u THEN
win.ontop:=FALSE;
windowlist[i]^:=win;
END(*IF*);
END(*IF*);
END(*FOR*);
END(*IF*);
END topWindow;
PROCEDURE MouseOn;
BEGIN
GrafMouse(257,NIL)
END MouseOn;
PROCEDURE MouseOff;
BEGIN
GrafMouse(256,NIL)
END MouseOff;
(* Vor Ausgaben auf den Bildschirm muss die Maus ausgeschaltet werden,
da sonst das Maussymbol überschrieben wird und bei der nächsten
Bewegung der Maus der alte, zuvor von der Maus verdeckte Bildschirm-
inhalt wieder restauriert wird. Alle Prozeduren in diesem Modul, die
den Bildschirm verändern, schalten die Maus während der Ausgabe aus.
Während des Aufrufs der vom Benutzer bereitgestellten Redraw-Prozedur
beim Abarbeiten der Rechteckliste in "DoRedraw" wird die Maus eben-
falls ausgeschaltet, ruft der Benutzer dagegen selbst seine Redraw-
Prozedur auf oder benutzt er die weiter unten beschriebenen Textaus-
gabeprozeduren, muss er sich selbst um die Maus kümmern.
Achtung: Ein- und Ausschalten der Maus wird vom Betriebssystem
mitgezählt. Wird die Maus mehrmals ausgeschaltet, muß
sie genausooft wieder eingeschaltet werden, damit sie
sichtbar wird. Wird die Maus zu oft eingeschaltet, dann
entstehen beim Bewegen von Fenstern und Schiebern Schmutz-
effekte.
*)
PROCEDURE High(a:ADDRESS):INTEGER;
VAR r : RECORD CASE : BOOLEAN OF
TRUE : w: ADDRESS;
|FALSE : h,l :INTEGER;
END(*CASE*);
END(*RECORD*);
BEGIN
r.w:=a;
RETURN r.h
END High;
PROCEDURE Low(a:ADDRESS):INTEGER;
VAR r:RECORD CASE : BOOLEAN OF
TRUE : w : ADDRESS;
|FALSE : h,l : INTEGER;
END(*CASE*);
END(*RECORD*);
BEGIN
r.w:=a;
RETURN r.l
END Low;
PROCEDURE SetInfo (u: window ; s: ARRAY OF CHAR);
VAR win :windowtype;
t :wstring;
i :INTEGER;
BEGIN
IF HIGH(s)>78 THEN
FOR i:= 0 TO 78 DO
t[i]:=s[i]
END(*FOR*);
t[79]:=0C
ELSE
FOR i:= 0 TO HIGH(s) DO
t[i]:=s[i]
END(*FOR*);
t[HIGH(s)+1]:=0C
END(*IF*);
IF windowlist[u] # NIL THEN
win:=windowlist[u]^;
win.info:=t;
windowlist[u]^:=win;
WindowSet(u,WindowInfo,High(ADR(windowlist[u]^.info)),
Low(ADR(windowlist[u]^.info)),0,0);
END(*IF*);
END SetInfo;
(* Schreibt einen Text in die Info-Zeile des Fensters *)
PROCEDURE SetTitle (u: window ; s: ARRAY OF CHAR);
VAR win :windowtype;
t : wstring;
i :INTEGER;
BEGIN
IF HIGH(s)>78 THEN
FOR i:= 0 TO 78 DO
t[i]:=s[i]
END(*FOR*);
t[79]:=0C
ELSE
FOR i:= 0 TO HIGH(s) DO
t[i]:=s[i]
END(*FOR*);
t[HIGH(s)+1]:=0C
END(*IF*);
IF windowlist[u] # NIL THEN
win:=windowlist[u]^;
win.title:=t;
windowlist[u]^:=win;
WindowSet(u,WindowName,High(ADR(windowlist[u]^.title)),
Low(ADR(windowlist[u]^.title)),0,0);
END(*IF*);
END SetTitle;
(* Schreibt einen Text in die Titel-Zeile des Fensters. Der Text
bleibt beim Schliessen erhalten und wird beim Öffnen wieder
angezeigt
*)
PROCEDURE SetHorSlider (u: window ; wpos, wsize, total: INTEGER);
VAR win :windowtype;
SliderSize,SliderPos :INTEGER;
BEGIN
IF windowlist[u] # NIL THEN
win:=windowlist[u]^;
MouseOff;
SliderSize:=wsize*1000 DIV total;
IF total <= wsize THEN
SliderPos := 0;
ELSE
SliderPos:=wpos*1000 DIV total
END(*IF*);
WindowSet(u,WindowHorizSlide,SliderPos,0,0,0);
WindowSet(u,HorizSliderSize,SliderSize,0,0,0);
MouseOn;
win.row:=wpos;win.maxrow :=total;
windowlist[u]^:=win;
END(*IF*);
END SetHorSlider;
(* siehe "SetVertSlider", setzt den horizontalen Schieber entsprechend
der horizontalen Position des Fensters im Gesamtdokument.
*)
PROCEDURE SetVertSlider (u: window ; wpos, wsize, total: INTEGER);
VAR win :windowtype;
SliderSize,SliderPos :INTEGER;
BEGIN
IF windowlist[u] # NIL THEN
win:=windowlist[u]^;
MouseOff;
SliderSize:=wsize*1000 DIV total;
IF total <= wsize THEN
SliderPos := 0;
ELSE
SliderPos:=wpos*1000 DIV total
END(*IF*);
WindowSet(u,WindowHorizSlide,SliderPos,0,0,0);
WindowSet(u,HorizSliderSize,SliderSize,0,0,0);
MouseOn;
win.col:=wpos;win.maxcol :=total;
windowlist[u]^:=win;
END(*IF*);
END SetVertSlider;
(* Berechnet die korrekte Position und -grösse des vertikalen
Schiebers aus den Parametern, die die vertikale Position des
Fensters im Gesamtdokument beschreiben, und setzt den Schieber.
Die Schieber müssen, falls vorhanden, nach jeder Veränderung
der Fenstergrösse oder des Fensterinhalts neu gesetzt werden.
Bedeutung der Parameter:
wpos: Anfangsposition des Fensters im Gesamtdokument
wsize: Grösse des im Fenster dargestellten Teils des Gesamtdokuments
total: Grösse des Gesamtdokuments
*)
PROCEDURE copyrect (u: window ; source, dest: rectangle);
VAR win : windowtype;
XYWH : BigPxyArrayType;
Screen1MFDB,Screen2MFDB : MFDBType;
x,y,w,h : INTEGER;
BEGIN
IF windowlist[u] # NIL THEN
win:=windowlist[u]^;
IF win.opened THEN
MouseOff;
WindowGet(u,WorkXYWH,x,y,w,h);
source.x:=source.x+x;source.y:=source.y+y;
dest.x:=dest.x+x;dest.y:=dest.y+y;
Screen1MFDB.pointer:=0D;
Screen1MFDB.width:=source.w;
Screen1MFDB.height:=source.h;
Screen1MFDB.format:=1;
Screen1MFDB.rsrvd1:=0; Screen1MFDB.rsrvd2:=0;
XYWH[0]:=source.x; XYWH[1]:=source.y; XYWH[2]:=source.w+source.x; XYWH[3]:=source.h+source.y;
XYWH[4]:=dest.x;XYWH[5]:=dest.y; XYWH[6]:=dest.w+dest.x;XYWH[7]:=dest.h+dest.y;
Screen2MFDB.pointer:=0D;
Screen2MFDB.width:=dest.w;
Screen2MFDB.height:=dest.h;
Screen2MFDB.format:=1;
Screen2MFDB.rsrvd1:=0; Screen2MFDB.rsrvd2:=0;
CopyRasterOpaque(handle,3,XYWH,ADR(Screen1MFDB),ADR(Screen2MFDB));
MouseOn;
END(*IF*);
END(*IF*);
END copyrect;
(* Kopiert innerhalb eines Fensters den Rechteckbereich "source" in
den Rechteckbereich "dest" (Koordinaten relativ zum Fensterursprung
links oben). Der freiwerdende Bereich von "source" muss bei Bedarf
gelöscht werden. Mit dieser Prozedur lassen sich Scroll-,
Insert- und Deletefunktionen in Textfenstern realisieren *)
PROCEDURE scrollup (u: window );
VAR win : windowtype;
r1,r2,r3 : rectangle;
BEGIN
IF windowlist[u] # NIL THEN
win:=windowlist[u]^;
IF win.opened THEN
r1:=win.work; r2:=win.work;
r1.x:=win.scrollX; r1.y:=win.scrollY;
r1.w:=r1.w-win.scrollX; r1.h:=r1.h-win.scrollY;
r2.x:=0;r2.y:=0;
r2.w:=r2.w-win.scrollX; r2.h:=r2.h-win.scrollY;
r3.x:=win.work.w-win.scrollX; r3.y:=win.work.w-win.scrollY;
r3.w:=win.scrollY; r3.h:=win.scrollY;
copyrect(u,r1,r2);
clearrect(u,r3);
win.row:=win.row+1;
windowlist[u]^:=win;
END(*IF*);
END(*IF*);
END scrollup;
(* Schiebt den Inhalt eines Textfensters eine Zeile nach oben, die
oberste Zeile verschwindet, die unterste wird gelöscht. "row"
wird auf "maxrow", "col" auf 0 gesetzt *)
PROCEDURE scrolldown (u: window );
VAR win : windowtype;
r1,r2,r3 : rectangle;
BEGIN
IF windowlist[u] # NIL THEN
win:=windowlist[u]^;
IF win.opened THEN
r1:=win.work; r2:=win.work;
r1.x:=win.scrollX; r1.y:=win.scrollY;
r1.w:=r1.w-win.scrollX; r1.h:=r1.h-win.scrollY;
r2.x:=0;r2.y:=0;
r2.w:=r2.w-win.scrollX; r2.h:=r2.h-win.scrollY;
r3.x:=0;r3.y:=0;
r3.w:=win.scrollX; r3.h:=win.scrollY;
copyrect(u,r2,r1);
clearrect(u,r3);
IF win.row >0 THEN
win.row:=win.row-1
ELSE
win.row:=0;
END(*IF*);
windowlist[u]^:=win;
END(*IF*);
END(*IF*);
END scrolldown;
(* Schiebt den Inhalt eines Textfenster eine Zeile nach unten, die
unterste Zeile verschwindet, die oberste wird gelöscht. "row"
und "col" werden auf 0 gesetzt *)
PROCEDURE DrawCursor (u:window ; row, col: INTEGER);
VAR win : windowtype;
XYWH : BigPxyArrayType;
ScreenMFDB : MFDBType;
x,y,w,h : INTEGER;
BEGIN
IF windowlist[u] # NIL THEN
win:=windowlist[u]^;
IF win.opened THEN
MouseOff;
WindowGet(u,WorkXYWH,x,y,w,h);
ScreenMFDB.pointer:=0D;
ScreenMFDB.width:=WC;
ScreenMFDB.height:=HC;
ScreenMFDB.format:=1;
ScreenMFDB.rsrvd1:=0; ScreenMFDB.rsrvd2:=0;
XYWH[0]:=x+row*WC; XYWH[1]:=y+row*HC; XYWH[2]:=XYWH[0]+HC; XYWH[3]:=XYWH[1]+WC;
XYWH[4]:=XYWH[0]; XYWH[5]:=XYWH[1]; XYWH[6]:=XYWH[2]; XYWH[7]:=XYWH[3];
CopyRasterOpaque(handle,12,XYWH,ADR(ScreenMFDB),ADR(ScreenMFDB));
MouseOn;
END(*IF*);
END(*IF*);
END DrawCursor;
(* Zeichnet ein Rechteck in der Grösse eines Zeichenfeldes an die
angegebene Stelle innerhalb des Fensters. Da alle Pixel inver-
tiert werden, nimmt ein zweiter Aufruf mit denselben Parametern
den Cursor wieder weg. *)
PROCEDURE WriteStr (u: window ; row, col: INTEGER; s: ARRAY OF CHAR);
VAR win : windowtype;
i,x,y,w,h: INTEGER;
Attributes : TextAttrArrayType;
BEGIN
IF windowlist[u] # NIL THEN
win:=windowlist[u]^;
IF win.opened THEN
MouseOff;
WindowGet(u,WorkXYWH,x,y,w,h);
x:=x+row*WC;
y:=y+col*HC;
InquireTextAttributes(handle,Attributes);
i:=SetGraphicTextColour(handle,win.textcolour);
i:=SetGraphicTextEffects(handle,VAL(INTEGER,win.texteffects));
GraphicText(handle,x,y,s);
i:=SetGraphicTextColour(handle,Attributes[1]);
i:=SetGraphicTextEffects(handle,0);
MouseOn;
END(*IF*);
END(*IF*);
END WriteStr;
(* Gibt einen String ab der durch "row" (Zeile) und "col" (Spalte)
angegebenen Stelle aus. Zeile und Spalte beziehen sich auf den
Arbeitsbereich des Fensters. Das Zeichen in der linken oberen
Ecke hat die Koordinaten (0,0). *)
PROCEDURE WriteTextBlock (u: window ; row, col: INTEGER;
adr: ADDRESS; count: INTEGER);
(* Wie "WriteStr", nur wird der auszugebende String durch die Adresse
des ersten Zeichens und die Länge angegeben
*)
END WriteTextBlock;
PROCEDURE WriteTextBuffer (u: window ; adr: ADDRESS;
count, offset: INTEGER);
(* Gibt den ab der Adresse "adr" liegenden Text ins Fenster "u" ab
der Position (0,0) aus, bis entweder 0C im Text auftritt, "count"
erreicht wird oder das Fenster voll ist. Als Zeilenende wird lf
erkannt, cr wird ignoriert. Falls "offset" > 0, werden die ersten
"offset" Zeichen in jeder Zeile übersprungen, so dass sich hori-
zontale Fensterverschiebungen realisieren lassen. Diese Prozedur
eignet sich gut für das Redrawing von Textfensterpuffern.
*)
END WriteTextBuffer;
PROCEDURE RectToPxy (VAR rect: rectangle; VAR pxy: PxyArrayType);
BEGIN
pxy[0]:=rect.x;
pxy[1]:=rect.y;
pxy[2]:=rect.x+rect.w;
pxy[3]:=rect.y+rect.h;
END RectToPxy;
PROCEDURE Intersect(r1:rectangle;VAR r2 :rectangle):BOOLEAN;
VAR r : rectangle;
PROCEDURE Min(a,b:INTEGER ):INTEGER;
BEGIN
IF a<b THEN RETURN a ELSE RETURN b END(*IF*);
END Min;
PROCEDURE Max(a,b:INTEGER ):INTEGER;
BEGIN
IF a>b THEN RETURN a ELSE RETURN b END(*IF*);
END Max;
BEGIN
r.w:=Min(r1.x+r1.w,r2.x+r2.w); r.h:=Min(r1.y+r1.h,r2.y+r2.h);
r.x:=Max(r1.x,r2.x);r.y:=Max(r1.y,r2.y);
r2:=r; r2.w:=r.w-r.x; r2.h:=r.h-r.y;
RETURN ((r.w>r.x) AND (r.h>r.y))
END Intersect;
PROCEDURE DoRedraw (u: window ; x, y, w, h: INTEGER; clip: BOOLEAN);
VAR r,r1 : rectangle;
pxy :PxyArrayType;
win : windowtype;
BEGIN
IF windowlist[u] # NIL THEN
win:=windowlist[u]^;
r1.x:=x;r1.y:=y;r1.h:=h;r1.w:=w;
MouseOff;
WindowUpdate(BeginUpdate);
WindowGet(u,FirstXYWH,r.x,r.y,r.w,r.h);
WHILE (r.w>0) AND (r.h>0) DO
IF Intersect(r1,r) THEN
r.w:=r.w-1; r.h:=r.h-1;
RectToPxy(r,pxy);
IF clip THEN
SetClipping(handle,1,pxy);
END(*IF*);
win.redrawproc(u,r);
END(*IF*);
WindowGet(u,NextXYWH,r.x,r.y,r.w,r.h);
END(*WHILE*);
pxy[0]:=0; pxy[1]:=0; pxy[2]:=0; pxy[3]:=0;
SetClipping(handle,0,pxy);
WindowUpdate(EndUpdate);
MouseOn;
END(*IF*);
END DoRedraw;
(* Holt sich von AES die Rechteckliste des Fensters w, schneidet die
erhaltenen Rechtecke mit dem Desktop und der als Parameter über-
gebenen Fläche und führt dann die erforderliche Anzahl von Auf-
rufen der Redraw-Prozedur, die beim Create-Aufruf angegeben wurde,
aus. "DoRedraw" ist somit die Aktion auf eine Redraw-Message. Mit
"clip" kann angegeben werden, ob "DoRedraw" selbst den Clipping-
Aufruf für VDI-Funktionen durchführen soll. In jedem Fall wird
während des Ablaufs von "DoRedraw" das Window-Update-Flag gesetzt
und die Maus ausgeschaltet.
*)
PROCEDURE wp (u: window ): windowptr;
BEGIN
RETURN windowlist[u];
END wp;
BEGIN
FOR Nil2Max := -1 TO maxwindow DO
windowlist[Nil2Max]:= NIL
END(*FOR*);
handle:=GrafHandle(WC,HC,WB,HB);
growbox:=TRUE;
Snap:=FALSE;
AllignX :=1;
AllignY :=1;
END EasyWindow.